package hu.mapro.gwtui.gxt.client.recordseditor.requestfactory;

import hu.mapro.gwtui.gxt.client.fieldseditor.FieldCreationInterface;
import hu.mapro.gwtui.gxt.client.fieldseditor.FieldsEditorComponent;
import hu.mapro.gwtui.gxt.client.fieldseditor.Initializer;
import hu.mapro.gwtui.gxt.client.fieldseditor.InstanceFieldsEditor;
import hu.mapro.gwtui.gxt.client.fieldseditor.Provider;
import hu.mapro.gwtui.gxt.client.fieldseditor.RequestContextInitializer;
import hu.mapro.gwtui.gxt.client.fieldseditor.TypeFieldsEditor;
import hu.mapro.gwtui.gxt.client.recordseditor.EditorInterface;
import hu.mapro.gwtui.shared.data.DataTypeUtils;

import java.util.List;

import com.google.gwt.editor.client.EditorError;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.requestfactory.gwt.client.RequestFactoryEditorDriver;
import com.google.web.bindery.requestfactory.shared.BaseProxy;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.RequestFactory;

public class TypeEditorAdapter<T extends BaseProxy> implements
		TypeFieldsEditor<T, RequestContextInitializer> {

	RequestFactoryEditorDriver<T, FieldsEditorComponent<T>> driver;
	Provider<T> fieldsEditorComponentProvider;
	RequestFactory requestFactory;
	
	FieldsEditorComponent<T> fieldsEditorComponent;
	FieldCreationInterface fieldCreationInterface;
	RequestContextInitializer requestContextInitializer;
	
	@Override
	public InstanceFieldsEditor<T, RequestContextInitializer> edit(final T object) {
		return new InstanceFieldsEditor<T, RequestContextInitializer>() {


			@Override
			public EditorInterface<T> initializer(
					final RequestContextInitializer initializer) {
				
				if (fieldsEditorComponent==null) {
					requestContextInitializer = initializer;
					initialize();
				}
				
				final T editing = requestContextInitializer.getCurrentRequestContext().edit(object);
				driver.edit(editing, requestContextInitializer.getCurrentRequestContext());
				
				return new EditorInterface<T>() {

					@Override
					public <Q> Q create(Class<Q> clazz) {
						return fieldCreationInterface.create(clazz);
					}

					@Override
					public T getEditingObject() {
						return editing;
					}

					@Override
					public boolean isDirty() {
						fieldsEditorComponent.checkDirty();
						return driver.isDirty();
					}

					@Override
					public List<EditorError> getErrors() {
						return driver.getErrors();
					}

					@Override
					public boolean hasErrors() {
						return driver.hasErrors();
					}

					@Override
					public void flush() {
						driver.flush();
					}

					@Override
					public Widget getWidget() {
						return fieldsEditorComponent;
					}

					@Override
					public void focus() {
						fieldsEditorComponent.focus();
					}
				};
			}
		};
	}

	protected void initialize() {
		fieldCreationInterface = new FieldCreationInterface() {
			@Override
			public <Q> Q create(Class<Q> clazz) {
				return DataTypeUtils.forRF(requestContextInitializer.getCurrentRequestContext()).create(clazz);
			}
		};
		fieldsEditorComponent = fieldsEditorComponentProvider.asFieldsEditorComponent(fieldCreationInterface);
		driver.initialize(requestFactory, fieldsEditorComponent);
	}

	public void setDriver(
			RequestFactoryEditorDriver<T, FieldsEditorComponent<T>> driver) {
		this.driver = driver;
	}

	public void setFieldsEditorComponentProvider(
			Provider<T> fieldsEditorComponentProvider) {
		this.fieldsEditorComponentProvider = fieldsEditorComponentProvider;
	}

	public void setRequestFactory(RequestFactory requestFactory) {
		this.requestFactory = requestFactory;
	}
	
}